﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace YangTools.Realization
{
    class LayerAttributes
    {
        private readonly Color defaultColor = Color.Black;
        private readonly int defaultMaterialIndex = -1;
        private const int totalColors = 16777216;

        /// <summary>
        /// 给图层区分颜色
        /// </summary>
        /// <param name="changeExisting">是否改变已经有了自定义颜色的图层</param>
        internal int RangeColor(bool changeExisting)
        {
            List<Rhino.DocObjects.Layer> layerToChange = Rhino.RhinoDoc.ActiveDoc.Layers.Where(l => !l.IsDeleted).ToList(); // 忽略已经删除的图层
            List<Color> ignoreColor = null;
            if (!changeExisting)
            {
                // 否则就是只改变那些颜色是默认值的，并记录要回避的颜色
                ignoreColor = layerToChange.Where(l => l.Color != defaultColor).Select(l => l.Color).ToList(); // 记录已有的颜色
                layerToChange = layerToChange.Where(l => l.Color == defaultColor).ToList();
            }

            List<Color> colors = GetRangedColor(layerToChange.Count, ignoreColor);
            for (int i = 0; i < layerToChange.Count; i++)
            {
                layerToChange[i].Color = colors[i];
            }

            return layerToChange.Count;
        }

        internal int RangeMaterial(bool changeExisting)
        {
            var materialTable = Rhino.RhinoDoc.ActiveDoc.Materials;
            List<Rhino.DocObjects.Layer> layerToChange = Rhino.RhinoDoc.ActiveDoc.Layers.Where(l => !l.IsDeleted).ToList(); // 忽略已经删除的图层
            List<Color> ignoreColor = null;

            if (!changeExisting)
            {
                // 否则就是只改变那些颜色是默认值的，并记录要回避的颜色
                ignoreColor = layerToChange.Where(l => l.RenderMaterialIndex != defaultMaterialIndex).Select(l => materialTable[l.RenderMaterialIndex].DiffuseColor).ToList(); // 记录已有的材质的漫反射颜色
                layerToChange = layerToChange.Where(l => l.RenderMaterialIndex == defaultMaterialIndex).ToList();
            }

            List<Color> colors = GetRangedColor(layerToChange.Count, ignoreColor);
            for (int i = 0; i < layerToChange.Count; i++)
            {
                var layer = layerToChange[i];
                var c = colors[i];
                int j = 0;
                string materialName;
                while (true)
                {
                    materialName = c.Name + "#" + j.ToString();
                    if (materialTable.Find(materialName, true) == -1)
                    {
                        break;
                    }
                    else
                    {
                        j++;
                    }
                }
                var m = new Rhino.DocObjects.Material() { Name = materialName, DiffuseColor = c };
                int newIndex = materialTable.Add(m);

                layer.RenderMaterialIndex = newIndex;
            }

            return layerToChange.Count;
        }

        /// <summary>
        /// 获取一定数量的互不相同的颜色
        /// </summary>
        /// <param name="count">个数</param>
        /// <param name="ignoreColor">避免出现的颜色</param>
        /// <returns></returns>
        private List<Color> GetRangedColor(int count, List<Color> ignoreColor)
        {
            List<Color> resultColor = new List<Color>();

            List<int> ignoreColorInt = ignoreColor != null ? ignoreColor.Select(c => ColorToInt(c)).ToList() : new List<int>(); // 先把回避颜色转换成十进制数
            int interval = totalColors / (ignoreColorInt.Count + count); // 颜色的间隔

            for (int i = 0; i < totalColors; i += interval)
            {
                if (ignoreColorInt.Any(ci => Math.Abs(ci - i) < interval))
                {
                    continue;
                }
                else
                {
                    resultColor.Add(IntToColor(i));
                }
                if (resultColor.Count == count) break;
            }

            if (resultColor.All(c => c.R == c.G || c.R == c.B || c.G == c.B))
            {
                return GetRangedColor(count + 1, ignoreColor).GetRange(0, count);
            }
            else
            {
                return resultColor;
            }

        }

        /// <summary>
        /// 将一个颜色（由RGB构成的256进制数）转换成十进制整数
        /// </summary>
        /// <param name="c">颜色</param>
        /// <returns>十进制数</returns>
        private int ColorToInt(Color c)
        {
            return c.B + c.G * 256 + c.R * 256 * 256;
        }
        /// <summary>
        /// 将一个十进制整数转换成一个颜色（由RGB构成的256进制数）
        /// </summary>
        /// <param name="num">要转换的数</param>
        /// <returns>颜色</returns>
        private Color IntToColor(int num)
        {
            int b;
            var n = Math.DivRem(num, 256, out b); // 十进制数除以 256 的余数就是 B 值
            int g;
            int r = Math.DivRem(n, 256, out g); // 上一次的数除以 256 的余数就是 G 值；因为只有三位，所以商就是 R
            return Color.FromArgb(r, g, b);
        }
    }
}
